//
// Created by 10741 on 2021/4/29.
//
#include <iostream>
#include <fstream>
#include <stack>
#include <utility>
#include <sstream>
#include "file.h"

using namespace std;

file::file(bool _isDir, file *_parent, string _fileName) : fileName(move(_fileName)){
    isDir = _isDir;
    parent = _parent;
}

file::file(const file &source, file *_parent) : fileName(source.fileName){
    isDir = source.isDir;
    parent = _parent;
    subFile = source.subFile;
    subDir = source.subDir;
    for(auto &i: subFile){
        i.second = new file(*i.second, this);
    }
    for(auto &i: subDir){
        i.second = new file(*i.second, this);
    }
}

int file::findName(string &theName){
    if(subFile.find(theName) != subFile.end()){
        return 2;
    }else if(subDir.find(theName) != subDir.end()){
        return 1;
    }else{
        return 0;
    }
}

void file::dir(){
    for(const auto &i: subFile){
        cout << i.first << "*\n";
    }
    for(const auto &i: subDir){
        cout << i.first << "\n";
    }
}

string file::absolutePath(){
    stack<file *> path;
    path.push(this);
    while(path.top()->parent != path.top()){
        path.push(path.top()->parent);
    }
    string res;
    path.pop();
    while(! path.empty()){
        res += '/';
        res += path.top()->fileName;
        path.pop();
    }
    if(res.empty()){ return "/"; }
    else{ return res; }
}

file::~file(){
    clear();
}

void file::save(ofstream &writer, int level, bool isCompressed){
    string leftBlank;
    string rightBlank;
    for(int i = 0; i < level * 2 and ! isCompressed; i ++){
        leftBlank += ' ';
    }
    if(!isCompressed)rightBlank += '\n';
    writer << leftBlank << "<name>" << fileName << "</name>" << rightBlank;
    if(isDir){
        for(auto i: subDir){
            writer << leftBlank << "<dir>" << rightBlank;
            i.second->save(writer, level + 1, isCompressed);
            writer << leftBlank << "</dir>" << rightBlank;
        }
        for(auto i: subFile){
            writer << leftBlank << "<file>" << rightBlank;
            i.second->save(writer, level + 1, isCompressed);
            writer << leftBlank << "</file>" << rightBlank;
        }
    }
}

void file::load(ifstream &reader){
    string content, tag;
    while(getline(reader, content, '<') and getline(reader, tag, '>')){
        stringstream theTag(tag);
        theTag >> tag;
        if(tag == "name"){
            getline(reader, content, '<');
            getline(reader, tag, '>');
            stringstream theFileName(content);
            theFileName >> fileName;
        }else if(tag == "dir"){
            file *newDir = new file(true, this);
            newDir->load(reader);
            subDir[newDir->fileName] = newDir;
        }else if(tag == "file"){
            file *newFile = new file(false, this);
            newFile->load(reader);
            subFile[newFile->fileName] = newFile;
        }else if(tag[0] == '/'){
            return;
        }else{
            int cnt = 1;
            while(cnt){
                getline(reader, content, '<');
                getline(reader, tag, '>');
                theTag.clear();
                theTag.str(tag);
                theTag >> tag;
                if(tag[0] == '/')cnt --;
                else cnt ++;
            }
        }
    }
}

void file::clear(){
    for(auto &i: subFile){
        delete i.second;
    }
    for(auto &i: subDir){
        delete i.second;
    }
}

void file::tree(string &s){
    int tot = subFile.size() + subDir.size();
    s += '|';
    for(const auto& i: subFile){
        if(tot == 1)s.back() = ' ';
        tot --;
        cout << s << "-- " << i.first << '*' << endl;
        s += "  ";
        i.second->tree(s);
        s.resize(s.size() - 2);
    }
    for(const auto& i: subDir){
        if(tot == 1)s.back() = ' ';
        tot --;
        cout << s << "-- " << i.first << endl;
        s += "   ";
        i.second->tree(s);
        s.resize(s.size() - 3);
    }
    s.pop_back();
}
